#! /usr/local/bin/python
"""
Author: Andy Nagels
Date: 2010-01-28
Alertlogger: Create logs of user defined events/values.

Copyright (C) 2010 Andy Nagels

This file is part of Alertlogger.

Alertlogger is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Alertlogger is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
					
"""

import sys, getopt, ConfigParser, time, datetime, os
from subprocess import call


class Alertlogger:
 
    def get_pprog(self):
        """ pprog """
        return self._pprog
    
    def set_pprog(self, name):
        """ set pprog """
        self._pprog = name
    
    pprog = property(get_pprog, set_pprog)
    
    def get_pversion(self):
        """ pversion """
        return self._pversion
    
    def set_pversion(self, version):
        """ set pversion """
        self._pversion = version
    
    pversion = property(get_pversion, set_pversion)
     
    def get_prelease(self):
        """ prelease """
        return self._prelease
    
    def set_prelease(self, release):
        """ set prelease """
        self._prelease = release
    
    prelease = property(get_prelease, set_prelease)
     
    def get_pdate(self):
        """ pdate """
        return self._pdate
    
    def set_pdate(self, date):
        """ set pdate """
        self._pdate = date
    
    pdate = property(get_pdate, set_pdate)
     
    def get_myconf(self):
        """ myconf """
        return self._myconf
    
    def set_myconf(self, version):
        """ set myconf """
        self._myconf = version
    
    myconf = property(get_myconf, set_myconf)
    
    def get_mydata(self):
        """ mydata """
        return self._mydata
    
    def set_mydata(self, version):
        """ set mydata """
        self._mydata = version
    
    mydata = property(get_mydata, set_mydata)
    
    def get_dmode(self):
        """ Daemon mode? """
        return self._dmode
    
    def set_dmode(self, mode):
        """ Daemon mode set """
        self._dmode = mode
    
    dmode = property(get_dmode, set_dmode)
 
    def get_dtimeout(self):
        """ Daemon mode timeout (sec)? """
        return self._dtimeout
    
    def set_dtimeout(self, time):
        """ Daemon mode set timeout (sec) """
        self._dtimeout = time
    
    dtimeout = property(get_dtimeout, set_dtimeout)
   
    def get_exitstate(self):
        """ Run or exit program? """
        return self._exitstate

    def set_exitstate(self, state):
        """ Set run-/exitstate """
        self._exitstate = state

    exitstate = property(get_exitstate, set_exitstate)
    
    def get_glog(self):
        """ Use global logfile? """
        return self._glog
    
    def set_glog(self, value):
        """ Set global logfile usage. """
        self._glog = value
    
    glog = property(get_glog, set_glog)
   
    def get_glogloc(self):
        """ Global log location.  """
        return self._glogloc
    
    def set_glogloc(self, value):
        """ Set global log location. """
        self._glogloc = value
    
    glogloc = property(get_glogloc, set_glogloc)
   
    def __init__(self):
        """ Init of main class """
        self.set_pprog('alertlogger.py')
        self.set_pversion('0.01a')
        self.set_prelease('Caveman')
        self.set_pdate('2010-01-28')
        self.set_myconf(self.fConfFile())
        self.set_mydata(self.fDataDir())
        self.fConfig()
        self.set_exitstate(0)
    
    def fConfFile(self):
        """ Get config file path from XDG_CONFIG_DIR. """
        # TODO: get from env var
        #self.set_myconf('~/.config/alertlogger/alertlogger.rc')
        return 'config/alertlogger/alertlogger.rc'
    
    def fDataDir(self):
        """ Get data file path from XDG_DATA_DIR. """
        # TODO: get from env var
        #self.set_mydata('~/.local/alertlogger/')
        return 'local/alertlogger/'

    def fUsage(self):
	    """ Print usage info and exit """
	    print self.get_pprog() + ''' : Cli application to create logs for user defined events.
	Options: 
	    -h : displays this help message
	    -d : start program in daemon mode (the timeout value is set in the configuration file)

	    --statistics : shows what logs are being created and shows program information
	    --version : displays version
	    --python : displays Python version
        Note: 
        Running the program without arguments, will execute it once. 
        Running it with -d, will continue to execute it.
        Adding another option will always exit the program with the desired message or information displayed, without running the main thread. This will render the -d option useless.
        See the man page for more information.'''

    def fConfig(self):
        """ Retrieve config file values """
        config = ConfigParser.RawConfigParser()
        config.read(self.get_myconf())

        daemonmode = config.get('main settings', 'daemonmode')
        self.set_dmode(daemonmode)        
        timeout = config.get('main settings', 'timeout')
        self.set_dtimeout(timeout)        
        log = config.get('logging', 'globallog')
        self.set_glog(log)        
        #self.get_glogloc() = "path/logfile" WITH double quotes! We remove them.
        location = config.get('logging', 'location')[1:-1]
        self.set_glogloc(location)        

    def fRun(self):
        """ This is the main driver for the program. """
        while True:
            # Exit when needed.
            if(self.get_exitstate()==1):
                sys.exit(0)
            
            # Test code.
            now = datetime.datetime.now()
            print now.strftime("%Y-%m-%d %H:%M:%S") + ": running main thread ..."
            # Look for alert files and execute them one by one.
            self.fAlerts()

            # Make sure we exit after first run, when not in daemon mode.
            # Wait for timeout, when in daemon mode.
            if(int(self.get_dmode())==0):
                self.set_exitstate(1)
            else:
                # timeout per alert-file??
                time.sleep(float(self.get_dtimeout()))
    
    def fAlerts(self):
        """ Loop through all alert-files. """
        # Importing alert-files needs a correct module path
        sys.path.append(self.get_mydata()) 

        for subdir, dirs, files in os.walk(self.get_mydata()):
            for file in files:
                if(file[-3:] == ".py"):
                    mdl = __import__(file[:-3])
                    x = mdl.Alert() # Create alert instance for current file.
                    if (int(x.get_enabled())==1):
                        x.fCommand() # This will generate the alert.
                        print x.get_alert() + " in file " + file
                        try:
                            
                            if(int(self.get_glog())==1):
                                print 'test-x: ' + self.get_glogloc() + '.'
                                logfile = open(self.get_glogloc(), "a")
                            else:
                                print 'test-xx: ' + x.get_logloc() + '.'
                                logfile = open(x.get_logloc(), "a")
                            try:
                                print 'test-xxx: ' + x.get_alert() + ' // '
                                # als timeout groter is in x, dan ev. write overslagen?
                                now = datetime.datetime.now()
                                logline = now.strftime("%Y-%m-%d %H:%M:%S") + ": " + x.get_alert()
                                logfile.write(logline + '\n')
                            finally:
                                logfile.close()
                        except IOError as (errno, strerror):
                            #pass
                            print "Error {0}: {1}".format(errno, strerror)
                    #else:
                        # This alert is disabled
                #else:
                    # Not a python file: ignore
        
    def fStats(self):
        """ Print statistic. """
        # Importing alert-files needs a correct module path
        sys.path.append(self.get_mydata()) 
        i = 0
        j = 0

        print "\nActive alert-scripts\n"
        print "---------------------\n"
        for subdir, dirs, files in os.walk(self.get_mydata()):
            for file in files:
                if(file[-3:] == ".py"):
                    j = j + 1
                    mdl = __import__(file[:-3])
                    x = mdl.Alert() # Create alert instance for current file.
                    if (int(x.get_enabled())==1):
                        i = i + 1
                        print str(i) + ". " + file + ":\n" + x.get_description()
                        if(int(self.get_glog())==0):
                            print 'Using custom logfile: ' + x.get_logloc() + '.\n'
                        else:
                            print 'Using global logfile: ' + self.get_glogloc() + '.\n'
        print "\n---------------------\n"
        print "Total amount of alert-scripts: " + str(j) + "."
        print "Total amount of active alert-scripts: " + str(i) + "."
        print "Total amount of inactive alert-scripts: " + str(j - i) + "."

    def fError(errno):
	    """ Exit with error. """
	    # All error descriptions should go here, apart from the getopt error in fMain.
	    switch = {
	    1: 'Error.',
	    2: 'Error2.',
	    3: 'Error3.',
	    -1: 'Unknown error.'
	    }
	    print switch[errno]
	    sys.exit(1)

def fMain():
    """ Main driver, startup and cli options parsing. """
    # Gonna switch this to optparse later
    try:
        options, xarguments = getopt.getopt(sys.argv[1:], 'hd', ['stats', 'version', 'python'])
    except getopt.error,err:
        print 'Error: ' + str(err)
        sys.exit(1)

    al = Alertlogger()

    for opt in options[:]:
        if opt[0] == '-h':
            al.fUsage()
            al.set_exitstate(1) # don't run the program after the optionparsing
    for opt in options[:]:
        if opt[0] == '-d':
            al.set_dmode(1)
            break
    for opt in options[:]:
        if opt[0] == '--stats':
            al.fStats()
            al.set_exitstate(1)
            break
    for opt in options[:]:
        if opt[0] == '--version':
            print al.get_pprog() + ' version '+ al.get_pversion() + ' (' + al.get_pdate() + '), \'' + al.get_prelease() + '\' release.'
            al.set_exitstate(1)
            break
    for opt in options[:]:
        if opt[0] == '--python':
            print 'Python '+sys.version
            al.set_exitstate(1)
            break

    if(al.get_exitstate() == 1):
        sys.exit(0)
    else:
        al.fRun() #run the main method for the program

if __name__ == "__main__":
    fMain()
